/* Copyright 2012 University of Ulm

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package de.uulm.inki.arqtest;

import java.net.URL;
import java.util.List;

import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.sparql.core.BasicPattern;
import com.hp.hpl.jena.sparql.engine.ExecutionContext;
import com.hp.hpl.jena.sparql.engine.QueryIterator;
import com.hp.hpl.jena.sparql.engine.main.QC;
import com.hp.hpl.jena.sparql.engine.main.StageGenerator;
import com.hp.hpl.jena.sparql.util.Context;
import com.hp.hpl.jena.sparql.util.Symbol;


public class InferenceStageGenerator implements StageGenerator {

    protected StageGenerator other;
    
    public InferenceStageGenerator(StageGenerator other){
        this.other = other ;
    }
    
    @SuppressWarnings("unused")
    public QueryIterator execute(BasicPattern pattern, QueryIterator input, ExecutionContext execCxt) {
        Context context=execCxt.getContext();
        Graph activeGraph=execCxt.getActiveGraph();
        Model model=ModelFactory.createModelForGraph(activeGraph);
        Reasoner reasoner;
        String semantics=context.get(Symbol.create("Semantics")).toString();
        if (semantics.equalsIgnoreCase(TestRunner.RDF_NS)) {
            reasoner=ReasonerRegistry.getRDFSSimpleReasoner();
        } else if (semantics.equalsIgnoreCase(TestRunner.RDFS_NS)) {
            URL rulesURL=getClass().getResource("/res/rules_fix.rules");
            List<Rule> rules = Rule.rulesFromURL(rulesURL.toExternalForm());
            reasoner=new GenericRuleReasoner(rules);
            ((GenericRuleReasoner)reasoner).setTransitiveClosureCaching(true);
//            reasoner=RDFSRuleReasonerFactory.theInstance().create(null);
//            reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel, ReasonerVocabulary.RDFS_FULL);
        } else if (semantics.equalsIgnoreCase(TestRunner.OWLRDFBASED_NS)) {
            reasoner=ReasonerRegistry.getOWLReasoner();
        } else {
            throw new UnsupportedOperationException("The semantics "+semantics+" is not supported");
        }
        InfModel infModel=ModelFactory.createInfModel(reasoner, model);
        infModel.prepare(); // just to be sure
        Graph infActiveGraph=infModel.getGraph();
        if (false) {
            StmtIterator iter = infModel.listStatements();
            while (iter.hasNext()) {
                Statement stmt      = iter.nextStatement();  // get next statement
                Resource  subject   = stmt.getSubject();     // get the subject
                Property  predicate = stmt.getPredicate();   // get the predicate
                RDFNode   object    = stmt.getObject();      // get the object
                System.out.print(subject.toString());
                System.out.print(" " + predicate.toString() + " ");
                if (object instanceof Resource) {
                    System.out.print(object.toString());
                } else {
                    // object is a literal
                    System.out.print(" \"" + object.toString() + "\"");
                }
                System.out.println(" .");
            } 
        }
        ExecutionContext newExecCxt=new ExecutionContext(context, infActiveGraph, execCxt.getDataset(), QC.getFactory(execCxt.getContext())) ;
        QueryIterator it=other.execute(pattern, input, newExecCxt);
        return it;
    }
}
